#include "inria_Data.h"

void CGroundTruthReader_INRIA::ReadGroundTruthFile(CSimpleTypeArray<CRectBox<int>>& dstGtDetectionList, string strFN_ImageGroundTruth)
{
	ifstream inStream(strFN_ImageGroundTruth.c_str());
	string st;
	char op;
	CRectBox<int> tBox;

	dstGtDetectionList.Clear();
	while (inStream>>st)
	{
		if (st!="Ymax)") continue;

		op = 0;
		for (    ;op!=':';) if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		for (    ;op!='(';) if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		st = ""; for (;;) { if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		if ((op>='0'&&op<='9')||op=='+'||op=='-') st += op; else break; } sscanf(st.c_str(), "%d", &tBox.x);
		for (    ;op!=',';) if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		st = ""; for (;;) { if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		if ((op>='0'&&op<='9')||op=='+'||op=='-') st += op; else break; } sscanf(st.c_str(), "%d", &tBox.y);
		for (    ;op!='(';) if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		st = ""; for (;;) { if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		if ((op>='0'&&op<='9')||op=='+'||op=='-') st += op; else break; } sscanf(st.c_str(), "%d", &tBox.w);
		for (    ;op!=',';) if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		st = ""; for (;;) { if (!(inStream>>op)) { inStream.clear(); inStream.close(); return; }
		if ((op>='0'&&op<='9')||op=='+'||op=='-') st += op; else break; } sscanf(st.c_str(), "%d", &tBox.h);

		//for (op=0;op!=':';inStream>>op);
		//for (op=0;op!='(';inStream>>op);
		//inStream>>tBox.x;
		//for (op=0;op!=',';inStream>>op);
		//inStream>>tBox.y;
		//for (op=0;op!='(';inStream>>op);
		//inStream>>tBox.w;
		//for (op=0;op!=',';inStream>>op);
		//inStream>>tBox.h;

		tBox.w -= tBox.x - 1;
		tBox.h -= tBox.y - 1;
		tBox.x -= 1;
		tBox.y -= 1;
		dstGtDetectionList.PushBack(tBox);
	}

	inStream.clear();
	inStream.close();
}

void CGroundTruthReader_INRIA::ReadWhiteGtFile(CRectBox<int>& dstRectBox, string strFN_GroundTruthImage)
{
	int ix, iy;
	CImg<int> imgSrc;

	CExternalTools::myLoadImage(strFN_GroundTruthImage.c_str(), imgSrc);
	dstRectBox.x = imgSrc.dimx();
	dstRectBox.y = imgSrc.dimy();
	dstRectBox.w = -1;
	dstRectBox.h = -1;
	for ( iy = 0; iy < imgSrc.dimy(); ++iy ) for ( ix = 0; ix < imgSrc.dimx(); ++ix )
	{
		if (imgSrc.at(ix, iy) < 127) continue;
		if (ix < dstRectBox.x) dstRectBox.x = ix;
		if (iy < dstRectBox.y) dstRectBox.y = iy;
		if (ix > dstRectBox.w) dstRectBox.w = ix;
		if (iy > dstRectBox.h) dstRectBox.h = iy;
	}
	dstRectBox.w -= dstRectBox.x - 1;
	dstRectBox.h -= dstRectBox.y - 1;
}

bool CDataSet_INRIA_IPPFE::CExample::CompareByImageIndexThenPosNegThenBox(const CExample& a, const CExample& b)
{
	if (a.ImageIndex != b.ImageIndex)
		return a.ImageIndex < b.ImageIndex;
	if (a.fIsPos != b.fIsPos)
		return a.fIsPos && !b.fIsPos;
	return a.ipp < b.ipp;
}

bool CDataSet_INRIA_IPPFE::CExample::InputFromStream(ifstream& inStream, const CPosNegFileNameSet& PosNegFileNameSet)
{
	int t;
	string st;

	if (!(inStream>>t>>st))
		return false;
	if (!ipp.InputFromStream(inStream))
		return false;
	fIsPos = (t==+1);
	if (fIsPos)
		ImageIndex = PosNegFileNameSet.PosList.GetFileIndex(st);
	else
		ImageIndex = PosNegFileNameSet.PosList.FileAmount + PosNegFileNameSet.NegList.GetFileIndex(st);
	return true;
}

void CDataSet_INRIA_IPPFE::CExample::OutputToStream(ofstream& outStream, const CPosNegFileNameSet& PosNegFileNameSet)
{
	if (fIsPos)
		outStream<<"+1\t"<<setw(4)<<PosNegFileNameSet.PosList.rgFN_Main[ImageIndex];
	else
		outStream<<"-1\t"<<setw(4)<<PosNegFileNameSet.NegList.rgFN_Main[ImageIndex - PosNegFileNameSet.PosList.FileAmount];
	ipp.OutputToStream(outStream);
	outStream<<endl;
}

void CDataSet_INRIA_IPPFE::myRelease()
{
	ExampleAmount = 0;
	CDataStructureTools::MyRelease_List(rgExample);
	CDataStructureTools::MyRelease_Single(_pIPPFE);
}

CDataSet_INRIA_IPPFE::CDataSet_INRIA_IPPFE()
{
	_cpPosNegFileNameSet = NULL;
	_strFN_LastImage = "";

	_pIPPFE = NULL;
	rgExample = NULL;
}

CDataSet_INRIA_IPPFE::~CDataSet_INRIA_IPPFE()
{
	myRelease();
}

void CDataSet_INRIA_IPPFE::myInit(string strNodeListFileName, const CPosNegFileNameSet* cpPosNegFileNameSet, CImageFilterBank* pIFB)
{
	int i;
	vector<CExample> tmpExampleList;
	CExample te;
	string st;

	myRelease();

	_cpPosNegFileNameSet = cpPosNegFileNameSet;

	ifstream inStream(strNodeListFileName.c_str());
	tmpExampleList.clear();
	ExampleAmount = 0;
	for (;;)
	{
		if (!te.InputFromStream(inStream,*_cpPosNegFileNameSet)) break;
		tmpExampleList.push_back(te);
		++ExampleAmount;
	}
	inStream.clear();
	inStream.close();

	rgExample = new CExample[ExampleAmount];
	for ( i = 0; i < ExampleAmount; ++i )
		rgExample[i] = tmpExampleList[i];
	sort(rgExample, rgExample + ExampleAmount, &CDataSet_INRIA_IPPFE::CExample::CompareByImageIndexThenPosNegThenBox);

#if USE_HOG
	_pIPPFE = C_IPPFE_Factory_HOG::GenerateIPPFE(1);
#else
	_pIPPFE = CFeatureFactory_ImageParse::GenerateIPPFE(pIFB, 1);
#endif

	_strFN_LastImage = "";
}

int CDataSet_INRIA_IPPFE::GetFeatureDimension()
{
	return _pIPPFE->GetFeatureDimension();
}

int CDataSet_INRIA_IPPFE::GetExampleAmount()
{
	return ExampleAmount;
}

int CDataSet_INRIA_IPPFE::GetExampleLabel(int NodeIndex)
{
	if (NodeIndex<0 || NodeIndex>=ExampleAmount)
		return 0;
	return (rgExample[NodeIndex].fIsPos ? +1 : -1);
}

double CDataSet_INRIA_IPPFE::GetExampleInitialWeight(int NodeIndex)
{
	return 1.0;
}

double CDataSet_INRIA_IPPFE::GetExampleFeature(int NodeIndex, int FeatureIndex)
{
	double ret = 0.0;

	if (NodeIndex<0 || NodeIndex>=ExampleAmount || FeatureIndex<0 || FeatureIndex>=_pIPPFE->GetFeatureDimension()) return ret;

	CExample& CurrentExample = rgExample[NodeIndex];
	int VMPosition = CurrentExample.ImageIndex;

	string strFN_SrcImage;
	if (CurrentExample.fIsPos)
		strFN_SrcImage = _cpPosNegFileNameSet->PosList.rgFN_SrcImage[CurrentExample.ImageIndex];
	else
		strFN_SrcImage = _cpPosNegFileNameSet->NegList.rgFN_SrcImage[CurrentExample.ImageIndex - _cpPosNegFileNameSet->PosList.FileAmount];
	if (strFN_SrcImage != _strFN_LastImage)
	{
		CImg<int> imgSrc;
		CExternalTools::myLoadImage(strFN_SrcImage, imgSrc);
		_pIPPFE->SetImage(imgSrc, "");

		_strFN_LastImage = strFN_SrcImage;
	}

	ret = _pIPPFE->GetFeature(CurrentExample.ipp, FeatureIndex);

	return ret;
}

